package com.slf.flow.oss.utils;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Item;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import com.slf.flow.oss.model.Oss;

import javax.activation.MimetypesFileTypeMap;
import javax.net.ssl.*;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.*;

public class MinioOSSUtil {
	
	/**
	 * 
	 * @Title: getMinioClient 
	 * @Description: 获取oss客户端 
	 * @return MinioClient oss客户端 
	 * @throws
	 */
	public static MinioClient getMinioClient(Oss oss) {
		return MinioClient.builder()
						.endpoint(oss.getEndpoint())
						.credentials(oss.getAccessKeyId(), oss.getAccessKeySecret())
						.build();
	}

	/**
	 * 
	 * @Title: uploadByNetworkStream 
	 * @Description: 通过网络流上传文件
	 * @param url 			URL 
	 * @param bucketName 	bucket名称 
	 * @param objectName 	上传文件目录和（包括文件名）例如“test/index.html” 
	 * @return void 		返回类型
	 * @throws
	 */
	public static void uploadByNetworkStream(MinioClient minioClient, URL url, String bucketName, String objectName) {
		try {
			InputStream inputStream = url.openStream();
			minioClient.putObject(
					PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
							inputStream, inputStream.available(), -1)
							.build());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (ErrorResponseException e) {
			e.printStackTrace();
		} catch (InvalidResponseException e) {
			e.printStackTrace();
		} catch (ServerException e) {
			e.printStackTrace();
		} catch (InvalidBucketNameException e) {
			e.printStackTrace();
		} catch (XmlParserException e) {
			e.printStackTrace();
		} catch (InternalException e) {
			e.printStackTrace();
		} catch (InsufficientDataException e) {
			e.printStackTrace();
		} finally {
//			if (minioClient != null) {
//				minioClient
//			}
		}
	}

	/**
	 * 
	 * @Title: uploadByInputStream 
	 * @Description: 通过输入流上传文件
	 * @param inputStream    输入流
	 * @param bucketName    bucket名称
	 * @param objectName    上传文件目录和（包括文件名） 例如“test/a.jpg”
	 * @throws
	 * @return
	 */
	public static ObjectWriteResponse uploadByInputStream(MinioClient minioClient, InputStream inputStream, String bucketName,
														  String objectName) {
		try {

			return minioClient.putObject(
					PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
							inputStream, inputStream.available(), -1)
							.build());
		} catch (Exception e) {
		} finally {
		}
		return null;
	}

	/**
	 * 
	 * @Title: uploadByFile 
	 * @Description: 通过file上传文件
	 * @param file            上传的文件
	 * @param bucketName    bucket名称
	 * @param objectName    上传文件目录和（包括文件名） 例如“test/a.jpg”
	 * @return void 		返回类型
	 * @throws
	 */
	public static ObjectWriteResponse uploadByFile(MinioClient minioClient, File file, String bucketName, String objectName) {
		try {
			InputStream inputStream = new FileInputStream(file);
			URLConnection connection = file.toURL().openConnection();
			String mimeType = connection.getContentType();
			return minioClient.putObject(
					PutObjectArgs.builder().bucket(bucketName).object(objectName).contentType(mimeType)
							.stream(
									inputStream, inputStream.available(), -1)
							.build());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
		return null;
	}


	/**
	 * 
	    * @Title: deleteFile  
	    * @Description: 根据key删除oss服务器上的文件
	    * @param key    		文件路径/名称，例如“test/a.txt”
	    * @return void    		返回类型  
	    * @throws
	 */
	public static void deleteFile(Oss oss, String key) {
		MinioClient minioClient = getMinioClient(oss);
		try {
			minioClient
					.removeObject(RemoveObjectArgs.builder().bucket(oss.getBucketName()).object(key).build());

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
	}

	/**
	 * 
	 * @Title: getInputStreamByOSS 
	 * @Description:根据key获取服务器上的文件的输入流
	 * @param bucketName 	bucket名称 
	 * @param key 			文件路径和名称 
	 * @return InputStream 	文件输入流
	 * @throws
	 */
	public static InputStream getInputStreamByOSS(MinioClient minioClient, String bucketName, String key) {
		InputStream content = null;
		try {
			content = minioClient
					.getObject(GetObjectArgs.builder().bucket(bucketName).object(key).build());
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return content;
	}

	/**
	 * 
	    * @Title: queryAllObject  
	    * @Description: 查询某个bucket里面的所有文件
	    * @param bucketName		bucket名称
	    * @return List<String>  文件路径和大小集合  
	    * @throws
	 */
	public static List<String> queryAllObject(MinioClient minioClient, String bucketName) {
		List<String> results = new ArrayList<String>();
		try {
			// MinioClient.listObjects返回ObjectListing实例，包含此次listObject请求的返回结果。
//			ObjectListing objectListing = minioClient.listObjects(bucketName);
			// objectListing.getObjectSummaries获取所有文件的描述信息。
//			List<Item> list = new ArrayList<>();
			Iterable<Result<Item>> objectsIterator = minioClient.listObjects(
					ListObjectsArgs.builder().bucket(bucketName).build());
			if (objectsIterator != null) {
				for (Result<Item> o : objectsIterator) {
					Item item = o.get();
					results.add(" - " + item.objectName() + "  " + "(size = " + item.size() + ")");
				}
			}
			return results;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
//			if (minioClient != null) {
//				MinioClient.shutdown();
//			}
		}
		return results;
	}
	
	/**
	 * 上传文件到oss
	 */
	public static Map<String, Object> uploadFileToOss(Oss oss,byte[] file,String filePath) {
		Map<String, Object> map = new HashMap<>();
		MinioClient minioClient = getMinioClient(oss);
		try {
			if (!minioClient.bucketExists(oss.getBucketName())) {	//是否存在名为“test”的bucket
				minioClient.makeBucket(oss.getBucketName());
			}
//			URLConnection connection = file.toURL().openConnection();
//			String mimeType = connection.getContentType();
			System.out.println("1111111111111111111111111111");
			uploadByInputStream(minioClient, new ByteArrayInputStream(file), oss.getBucketName(), filePath);
			map.put("size",file.length);
			map.put("path",filePath);
			map.put("url",minioClient.presignedGetObject(oss.getBucketName(), filePath));
			String[] fps = filePath.split("/");
			map.put("name",fps[fps.length - 1]);
			return map;
		} catch (Exception e) {
			try {
				throw e;
			} catch (ErrorResponseException ex) {
				ex.printStackTrace();
			} catch (InsufficientDataException ex) {
				ex.printStackTrace();
			} catch (InternalException ex) {
				ex.printStackTrace();
			} catch (InvalidBucketNameException ex) {
				ex.printStackTrace();
			} catch (InvalidExpiresRangeException ex) {
				ex.printStackTrace();
			} catch (InvalidKeyException ex) {
				ex.printStackTrace();
			} catch (InvalidResponseException ex) {
				ex.printStackTrace();
			} catch (IOException ex) {
				ex.printStackTrace();
			} catch (NoSuchAlgorithmException ex) {
				ex.printStackTrace();
			} catch (ServerException ex) {
				ex.printStackTrace();
			} catch (XmlParserException | RegionConflictException ex) {
				ex.printStackTrace();
			}
		}
		return null;
	}
	/**
	 * 上传文件到oss
	 */
	public static Map<String, Object> uploadFileToOss(Oss oss,String urlString,String filePath) {
		Map<String, Object> map = new HashMap<>();
		MinioClient minioClient = getMinioClient(oss);
		HttpsURLConnection conn = null;
		HttpURLConnection connection = null;
		InputStream is = null;
		try {
			//是否存在名为“test”的bucket
			if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(oss.getBucketName()).build())) {
				minioClient.makeBucket(MakeBucketArgs.builder().bucket(oss.getBucketName()).build());
			}
			URL url = new URL(urlString);
			if(urlString.indexOf("https") > -1){
				TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
					@Override
					public java.security.cert.X509Certificate[] getAcceptedIssuers() {
						return null;
					}
					@Override
					public void checkClientTrusted(X509Certificate[] certs, String authType) {
					}
					@Override
					public void checkServerTrusted(X509Certificate[] certs, String authType) {
					}
				}
				};
				SSLContext sc = SSLContext.getInstance("SSL");
				sc.init(null, trustAllCerts, new java.security.SecureRandom());
				HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
				HostnameVerifier allHostsValid = new HostnameVerifier(){
					@Override
					public boolean verify(String hostname, SSLSession session) {
						return true;
					}

				};
				HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
				//打开连接
				conn = (HttpsURLConnection) url.openConnection();
				//设置请求方式为"GET"
				conn.setRequestMethod("GET");
//        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
				conn.setRequestProperty("User-Agent", "Mozilla/4.76");
				//超时响应时间为10秒
				conn.setConnectTimeout(10 * 1000);
				//通过输入流获取图片数据

				SSLSocketFactory sslSocketFactory = sc.getSocketFactory();
				conn.setSSLSocketFactory(sslSocketFactory);
				is = conn.getInputStream();
				map.put("size",conn.getContentLength());
			}else{
				connection = (HttpURLConnection) url.openConnection();
				connection.setRequestProperty("User-Agent", "Mozilla/4.76");
				//超时响应时间为10秒
				connection.setConnectTimeout(10 * 1000);
				is = connection.getInputStream();
				map.put("size",connection.getContentLength());
			}

			byte[] bytes = readInputStream(is);
			ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
			if(filePath.endsWith("/")){
				filePath += FilenameUtils.getName(url.getPath());
			}
//			System.out.println(URLConnection.guessContentTypeFromStream(byteArrayInputStream));
			String probeContentType = "";
			try {
				Path path = Paths.get(urlString);
				probeContentType = Files.probeContentType(path);
			}catch (Exception e){
				System.err.println(e.getMessage());
			}
			if(StringUtils.isEmpty(probeContentType)){
				try {
					ContentInfo info1 = ContentInfoUtil.findExtensionMatch(urlString);
					probeContentType = info1.getMimeType();
				}catch (Exception e){
					System.err.println(e.getMessage());
				}
			}
			System.out.println(probeContentType);
			minioClient.putObject(
					PutObjectArgs.builder()
							.bucket(oss.getBucketName()).object(filePath).contentType(probeContentType)
							.stream(byteArrayInputStream,byteArrayInputStream.available(),PutObjectArgs.MIN_MULTIPART_SIZE)
							.build());

//			minioClient.putObject(PutObjectArgs.builder()
//					.bucket(bucket).object(objectKey)
//					.stream(stream, stream.available(),PutObjectArgs.MIN_MULTIPART_SIZE)
//					.contentType(contentType).build());




			map.put("path", filePath);
			;
//			map.put("url",minioClient.presignedGetObject(oss.getBucketName(),filePath));
			map.put("name",FilenameUtils.getName(url.getPath()));
			return map;
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(conn!=null){
				try {
					conn.disconnect();
				}catch (Exception e){
					System.err.println("关闭空数据！");
				}

			}
			if(connection!=null){
				try {
					connection.disconnect();
				}catch (Exception e){
					System.err.println("关闭空数据！");
				}
			}
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
		return null;
	}


	public static byte[] readInputStream(InputStream inStream) throws Exception {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		//创建一个Buffer字符串
		byte[] buffer = new byte[6024];
		//每次读取的字符串长度，如果为-1，代表全部读取完毕
		int len;
		//使用一个输入流从buffer里把数据读取出来
		while ((len = inStream.read(buffer)) != -1) {
			//用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
			outStream.write(buffer, 0, len);
		}
		//关闭输入流
		inStream.close();
		//把outStream里的数据写入内存
		return outStream.toByteArray();
	}
	public static String uploadByUrl(Oss oss, String url) {
		MinioClient minioClient = getMinioClient(oss);
		if (StringUtils.isBlank(url)) {
			return null;
		}
		try {
			InputStream inputStream = FileUtils.returnBitMap(url);
			// 判断上传文件是否为空
			if (null == inputStream) {
				System.out.println("获取流为空！！！");
				return null;
			}
			Path temp = Files.createTempFile("resource-", ".PNG");
			Files.copy(inputStream, temp, StandardCopyOption.REPLACE_EXISTING);
			FileInputStream in = new FileInputStream(temp.toFile());
			// 判断存储桶是否存在，不存在则创建
//			createBucket(MinioConst.MINIO_BUCKET);
			// uuid 生成文件名
			String uuid = String.valueOf(UUID.randomUUID());
			// 新的文件名
			String fileName = "wxAvatar/" + uuid + ".jpg";
			// 开始上传
			minioClient.putObject(
					PutObjectArgs.builder()
							.bucket(oss.getBucketName()).object(fileName)
							.contentType(getContentType(url))
							.stream(in,in.available(),PutObjectArgs.MIN_MULTIPART_SIZE)
							.build());
//			minioClient.putObject(oss.getBucketName(), fileName, inputStream, "jpg");
			// 返回图片的访问路径
			return fileName;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
//		uploadFileMinio();
		String urlString = "https://www.navalnews.com/wp-content/uploads/2023/05/BRP-Gener-Tinangag-PG903-770x410.jpg.webp";
		String probeContentType = Files.probeContentType(Paths.get(urlString));
		System.out.println(probeContentType);
		ContentInfo info1 = ContentInfoUtil.findExtensionMatch(urlString);
		String contentType1 = info1.getMimeType();
		System.out.println(contentType1);
	}
	public static String uploadFileMinio(){
		try {
			//创建MinioClient对象
			MinioClient minioClient = MinioClient.builder()
					.endpoint("http://192.168.0.182:9000/")
					.credentials("xingdaousername", "xingdaopassword")
					.build();

//			File file = new File("/Users/mr.cheng/Desktop/gts/banner.png");
//			InputStream in = new FileInputStream(file);
			//定义一个URL对象，就是你想下载的图片的URL地址
			URL url = new URL("https://www.unmannedsystemstechnology.com/wp-content/uploads/2022/04/Auterion-Elsight.webp");
			//打开连接
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			//设置请求方式为"GET"
			conn.setRequestMethod("GET");
//        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
			conn.setRequestProperty("User-Agent", "Mozilla/4.76");
			//超时响应时间为10秒
			conn.setConnectTimeout(10 * 1000);
			//通过输入流获取图片数据
			Path temp = Files.createTempFile("resource-", ".PNG");
			Files.copy(conn.getInputStream(), temp, StandardCopyOption.REPLACE_EXISTING);
			FileInputStream in = new FileInputStream(temp.toFile());
			String fileName = "Auterion-Elsight1.webp";
			//文件上传到minio上的Name把文件后缀带上，不然下载出现格式问题
//			fileName = UUID.randomUUID()+"."+fileName.substring(fileName.lastIndexOf(".") + 1);

			//创建头部信息
			Map<String, String> headers = new HashMap<>(10);
			//添加自定义内容类型
			headers.put("Content-Type", "application/octet-stream");
			//添加存储类
			headers.put("X-Amz-Storage-Class", "REDUCED_REDUNDANCY");
			//添加自定义/用户元数据
			Map<String, String> userMetadata = new HashMap<>(10);
			userMetadata.put("My-Project", "Project One");
			//上传
			minioClient.putObject(
					PutObjectArgs.builder().bucket("back").object("wxAvatar/"+fileName).stream(
									in, in.available(), -1)
							.headers(headers)
							.userMetadata(userMetadata)
							.build());
			in.close();
			return fileName;
		}catch (Exception e){
			e.printStackTrace();
			return e.getMessage();
		}
	}
	public static String getContentType(String fileUrl) {
		String contentType = null;
		try {
			contentType = new MimetypesFileTypeMap().getContentType(new File(fileUrl));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("getContentType, File ContentType is : " + contentType);
		return contentType;
	}
	public String getPreviewFileUrl(Oss oss,MinioClient minioClient, String fileName) {
		try {
			return minioClient.getObjectUrl(oss.getBucketName(),fileName);
		}catch (Exception e){
			e.printStackTrace();
			return "";
		}
	}

	public static InputStream downloadFile(Oss oss, String originalName, HttpServletResponse response) {
		try {
			MinioClient minioClient = getMinioClient(oss);
			InputStream file = minioClient.getObject(oss.getBucketName(), originalName);
			String filename = new String(originalName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
//			if (StrUtil.isNotBlank(originalName)) {
//				filename = originalName;
//			}
			response.setHeader("Content-Disposition", "attachment;filename=" + filename);
			ServletOutputStream servletOutputStream = response.getOutputStream();
			int len;
			byte[] buffer = new byte[1024];
			while ((len = file.read(buffer)) > 0) {
				servletOutputStream.write(buffer, 0, len);
			}
			servletOutputStream.flush();
			file.close();
			servletOutputStream.close();
			return file;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}